#include "fram.h"
#include "usart.h"
#include <string.h>
#include <stdio.h>

// 存储管理结构实例
static storage_manager_t storage_mgr;

// 内部函数声明
static bool FRAM_CS_Low(void);
static bool FRAM_CS_High(void);
static bool FRAM_SendCommand(uint8_t command);
static bool FRAM_SendAddress(uint16_t address);
static bool FRAM_WaitForReady(void);

/**
 * @brief 初始化FRAM
 * @retval true: 成功, false: 失败
 */
bool FRAM_Init(void)
{
    // 配置CS引脚为输出，cs记为chip select
    GPIO_InitTypeDef GPIO_InitStruct = {0};
    
    __HAL_RCC_GPIOA_CLK_ENABLE();
    
    GPIO_InitStruct.Pin = GPIO_PIN_0;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
    
    // CS初始状态为高电平，高电平表示未选中FRAM
    FRAM_CS_High();
    
    // 等待FRAM上电稳定
    HAL_Delay(10);
    
    // 读取状态寄存器验证通信，验证SPI通信是否正常
    uint8_t status = FRAM_ReadStatus();
    printf("FRAM Status: 0x%02X\r\n", status);
    
    // 初始化存储管理器
    if (!FRAM_InitStorage()) {
        printf("FRAM Storage init failed\r\n");
        return false;
    }
    
    printf("FRAM initialized successfully\r\n");
    return true;
}

/**
 * @brief 写使能
 * @retval true: 成功, false: 失败
 */
bool FRAM_WriteEnable(void)
{
    return FRAM_SendCommand(FRAM_WREN);
}

/**
 * @brief 写禁止
 * @retval true: 成功, false: 失败
 */
bool FRAM_WriteDisable(void)
{
    return FRAM_SendCommand(FRAM_WRDI); //WRDI为写禁止指令
}

/**
 * @brief 读取状态寄存器
 * @retval 状态寄存器值
 */
uint8_t FRAM_ReadStatus(void)
{
    uint8_t status = 0;
    
    if (FRAM_CS_Low()) { //将PA0置零，即选中FRAM
        FRAM_SendCommand(FRAM_RDSR); //发送指令，RDSR为读取状态寄存器
        HAL_SPI_Receive(&hspi1, &status, 1, 1000);
        FRAM_CS_High();
        return status;
    }
    return 0xFF;
}

/**
 * @brief 写状态寄存器
 * @param status: 状态值
 * @retval true: 成功, false: 失败
 */
bool FRAM_WriteStatus(uint8_t status)
{
    if (!FRAM_WriteEnable()) return false;
    
    if (FRAM_CS_Low()) {
        FRAM_SendCommand(FRAM_WRSR);
        HAL_SPI_Transmit(&hspi1, &status, 1, 1000);
        FRAM_CS_High();
        return true;
    }
    return false;
}

/**
 * @brief 读取数据
 * @param address: 地址
 * @param data: 数据缓冲区
 * @param length: 数据长度
 * @retval true: 成功, false: 失败
 */
bool FRAM_Read(uint16_t address, uint8_t *data, uint16_t length) //从存储器中读取数据
{
    if (address + length > FRAM_SIZE) return false;
    
    if (FRAM_CS_Low()) {
        FRAM_SendCommand(FRAM_READ);
        FRAM_SendAddress(address);
        HAL_SPI_Receive(&hspi1, data, length, 1000);
        FRAM_CS_High();
        return true;
    }
    return false;
}

/**
 * @brief 写入数据
 * @param address: 地址
 * @param data: 数据缓冲区
 * @param length: 数据长度
 * @retval true: 成功, false: 失败
 */
bool FRAM_Write(uint16_t address, uint8_t *data, uint16_t length)
{
    if (address + length > FRAM_SIZE) return false;
    
    if (!FRAM_WriteEnable()) return false;
    
    if (FRAM_CS_Low()) {
        FRAM_SendCommand(FRAM_WRITE);
        FRAM_SendAddress(address);
        HAL_SPI_Transmit(&hspi1, data, length, 1000);
        FRAM_CS_High();
        return true;
    }
    return false;
}

/**
 * @brief 读取单字节
 * @param address: 地址
 * @param data: 数据指针
 * @retval true: 成功, false: 失败
 */
bool FRAM_ReadByte(uint16_t address, uint8_t *data)
{
    return FRAM_Read(address, data, 1);  //FRAM_Read从address读取数据，此时data为地址，注意和下面区分
}

/**
 * @brief 写入单字节
 * @param address: 地址
 * @param data: 数据
 * @retval true: 成功, false: 失败
 */
bool FRAM_WriteByte(uint16_t address, uint8_t data)
{
    return FRAM_Write(address, &data, 1);  //FRAM_Write从data的地址读取数据，并放到address地址处的位置
}

/**
 * @brief 擦除所有数据
 * @retval true: 成功, false: 失败
 */
bool FRAM_EraseAll(void) //从第一位开始，将FRAM写0
{
    uint8_t zero = 0;
    for (uint16_t i = 0; i < FRAM_SIZE; i++) {
        if (!FRAM_WriteByte(i, zero)) {
            return false;
        }
    }
    return true;
}

/**
 * @brief 初始化存储管理器
 * @retval true: 成功, false: 失败
 */
bool FRAM_InitStorage(void)
{
    // 读取存储管理器信息
    uint8_t header[8];
    if (!FRAM_Read(0, header, 8)) {
        return false;
    }
    
    // 检查魔数 (   55)
    if (header[0] == 0xAA && header[1] == 0x55) {
        // 有效的存储管理器
        storage_mgr.write_index = (header[2] << 8) | header[3];
        storage_mgr.read_index = (header[4] << 8) | header[5];
        storage_mgr.data_count = (header[6] << 8) | header[7];
        storage_mgr.max_records = (FRAM_SIZE - 8) / sizeof(sensor_data_t);
        
        printf("FRAM Storage: write_index=%d, read_index=%d, data_count=%d, max_records=%d\r\n",
               storage_mgr.write_index, storage_mgr.read_index, storage_mgr.data_count, storage_mgr.max_records);
    } else {
        // 初始化新的存储管理器
        storage_mgr.write_index = 0;
        storage_mgr.read_index = 0;
        storage_mgr.data_count = 0;
        storage_mgr.max_records = (FRAM_SIZE - 8) / sizeof(sensor_data_t);
        
        // 写入魔数和初始值
        header[0] = 0xAA;
        header[1] = 0x55;
        header[2] = (storage_mgr.write_index >> 8) & 0xFF;
        header[3] = storage_mgr.write_index & 0xFF;
        header[4] = (storage_mgr.read_index >> 8) & 0xFF;
        header[5] = storage_mgr.read_index & 0xFF;
        header[6] = (storage_mgr.data_count >> 8) & 0xFF;
        header[7] = storage_mgr.data_count & 0xFF;
        
        if (!FRAM_Write(0, header, 8)) {
            return false;
        }
        
        printf("FRAM Storage initialized: max_records=%d\r\n", storage_mgr.max_records);
    }
    
    return true;
}

/**
 * @brief 保存传感器数据
 * @param data: 传感器数据
 * @retval true: 成功, false: 失败
 */
bool FRAM_SaveSensorData(sensor_data_t *data)
{
    if (data == NULL) return false;
    
    // 计算数据存储地址,固定8字节（头部）+数据偏移量，write_index即当前写的位置的索引值，因为每条数据的大小都是固定的，所以通过这种方式
    uint16_t data_addr = 8 + (storage_mgr.write_index * sizeof(sensor_data_t));
    
    // 写入数据
    if (!FRAM_Write(data_addr, (uint8_t*)data, sizeof(sensor_data_t))) {
        return false;
    }
    
    // 更新索引
    storage_mgr.write_index++;
    if (storage_mgr.write_index >= storage_mgr.max_records) {
        storage_mgr.write_index = 0; // 循环覆盖
    }
    
    // 更新数据计数
    if (storage_mgr.data_count < storage_mgr.max_records) {
        storage_mgr.data_count++;
    }
    
    // 更新存储管理器信息，将这些信息放到FRAM的最开始8位
    uint8_t header[8];
    header[0] = 0xAA;
    header[1] = 0x55;
    header[2] = (storage_mgr.write_index >> 8) & 0xFF;
    header[3] = storage_mgr.write_index & 0xFF;
    header[4] = (storage_mgr.read_index >> 8) & 0xFF;
    header[5] = storage_mgr.read_index & 0xFF;
    header[6] = (storage_mgr.data_count >> 8) & 0xFF;
    header[7] = storage_mgr.data_count & 0xFF;
    
    return FRAM_Write(0, header, 8);//写入FRAM前八位
}

/**
 * @brief 读取传感器数据
 * @param index: 数据索引
 * @param data: 数据缓冲区
 * @retval true: 成功, false: 失败
 */
bool FRAM_ReadSensorData(uint16_t index, sensor_data_t *data)
{
    if (data == NULL || index >= storage_mgr.data_count) 
        return false;
     
    // 计算实际存储索引
    uint16_t actual_index = (storage_mgr.read_index + index) % storage_mgr.max_records;
    uint16_t data_addr = 8 + (actual_index * sizeof(sensor_data_t));
    
    return FRAM_Read(data_addr, (uint8_t*)data, sizeof(sensor_data_t));
}

/**
 * @brief 获取数据数量
 * @retval 数据数量
 */
uint16_t FRAM_GetDataCount(void)
{
    return storage_mgr.data_count;
}

/**
 * @brief 清除所有数据
 * @retval true: 成功, false: 失败
 */
bool FRAM_ClearAllData(void)
{
    storage_mgr.write_index = 0;
    storage_mgr.read_index = 0;
    storage_mgr.data_count = 0;
    
    // 更新存储管理器信息
    uint8_t header[8];
    header[0] = 0xAA;
    header[1] = 0x55;
    header[2] = 0;
    header[3] = 0;
    header[4] = 0;
    header[5] = 0;
    header[6] = 0;
    header[7] = 0;
    
    return FRAM_Write(0, header, 8);
}

/**
 * @brief 获取最新数据
 * @param data: 数据缓冲区
 * @retval true: 成功, false: 失败
 */
bool FRAM_GetLatestData(sensor_data_t *data)
{
    if (storage_mgr.data_count == 0) return false;
    
    uint16_t latest_index = (storage_mgr.write_index - 1 + storage_mgr.max_records) % storage_mgr.max_records;
    uint16_t data_addr = 8 + (latest_index * sizeof(sensor_data_t));
    
    return FRAM_Read(data_addr, (uint8_t*)data, sizeof(sensor_data_t));
}

/**
 * @brief 保存24小时数据
 * @param data: 传感器数据
 * @retval true: 成功, false: 失败
 */
bool FRAM_Save24HourData(sensor_data_t *data)
{
    return FRAM_SaveSensorData(data);
}

/**
 * @brief 获取24小时数据
 * @param data: 数据缓冲区
 * @param max_count: 最大数据条数
 * @param actual_count: 实际数据条数
 * @retval true: 成功, false: 失败
 */
bool FRAM_Get24HourData(sensor_data_t *data, uint16_t max_count, uint16_t *actual_count)
{
    if (data == NULL || actual_count == NULL) return false;
    
    uint16_t count = (max_count < storage_mgr.data_count) ? max_count : storage_mgr.data_count;
    *actual_count = 0;
    
    for (uint16_t i = 0; i < count; i++) {
        if (FRAM_ReadSensorData(i, &data[i])) {
            (*actual_count)++;
        } else {
            break;
        }
    }
    
    return (*actual_count > 0);
}

/**
 * @brief 检查是否有24小时数据
 * @retval true: 有数据, false: 无数据
 */
bool FRAM_Is24HourDataAvailable(void)
{
    return (storage_mgr.data_count > 0);
}

// 内部函数实现

/**
 * @brief CS信号拉低
 * @retval true: 成功, false: 失败
 */
static bool FRAM_CS_Low(void)
{
    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, GPIO_PIN_RESET);
    return true;
}

/**
 * @brief CS信号拉高
 * @retval true: 成功, false: 失败
 */
static bool FRAM_CS_High(void)
{
    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, GPIO_PIN_SET);
    return true;
}

/**
 * @brief 发送命令
 * @param command: 命令字节
 * @retval true: 成功, false: 失败
 */
static bool FRAM_SendCommand(uint8_t command)
{
    return (HAL_SPI_Transmit(&hspi1, &command, 1, 1000) == HAL_OK); //如果HAL_SPI_Transmit的返回值为HAL_OK，即发送成功，则FRAM_SendCommand返回TRUE，是这样的逻辑

}

/**
 * @brief 发送地址
 * @param address: 16位地址
 * @retval true: 成功, false: 失败
 */
static bool FRAM_SendAddress(uint16_t address)
{
    uint8_t addr_bytes[2];
    addr_bytes[0] = (address >> 8) & 0xFF; //得到地址的高八位
    addr_bytes[1] = address & 0xFF; //得到地址的低八位
    return (HAL_SPI_Transmit(&hspi1, addr_bytes, 2, 1000) == HAL_OK);
}

/**
 * @brief 等待FRAM就绪
 * @retval true: 成功, false: 失败
 */
static bool FRAM_WaitForReady(void)
{
    uint8_t status;
    uint32_t timeout = 1000;
    
    while (timeout--) {
        status = FRAM_ReadStatus();
        if (!(status & FRAM_SR_BUSY)) {
            return true;
        }
        HAL_Delay(1);
    }
    return false;
} 
